/*	--- 最佳实践 --- 

由于Java提供了新旧两套日期和时间的API，除非涉及到遗留代码，否则我们应该坚持使用新的API。

如果需要与遗留代码打交道，如何在新旧API之间互相转换呢？


----------------------------------


#	旧API -> 新API

如果要把旧式的Date或Calendar转换为新API对象，可以通过toInstant()方法转换为Instant对象，再通过Instant继续转换为ZonedDateTime：	*/

Instant ins = new Date.toInstant(); // Instant是传递中介

// Calendar -> Instant -> ZonedDateTime
Calendar calendar = Calendar.getInstance(); // Calendar
Instance ins2 = Calendar.getInstance().toInstant(); // Calendar -> Instant
ZonedDateTime zdt = ins2.atZone(calendar.getTimeZone().toZoneId());
	// Instant(Calendar) + .atZone() -> ZonedDateTime

// 从上面的代码还可以看到，旧的TimeZone提供了一个toZoneId()，可以把自己变成新的ZoneId。


/*	------------------------------------



# 新API -> 旧API


如果要把新的ZonedDateTime转换为旧的API对象，只能借助'long型时间戳'做一个"中转"： */

ZonedDateTime zdt = ZonedDateTime.now();
long ts = zdt.toEpochSecond() * 1000; // ZonedDateTime -> long(要 * 1000)

// long -> Date
Date date = new Date(ts); // Date(long EpochSecond)

// long -> Calendar
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.setTimeZone(TimeZone.getTimeZone(zdt.getZone().getId()));

calendar.setTimeInMillis(zdt.toEpochSecond() * 1000);
calendar.setTimeInMillis(ts); // 同上


// 从上面的代码还可以看到，新的ZoneId转换为旧的TimeZone，需要借助ZoneId.getId()返回的String完成。




/* ---------------------------------------------------



# 在数据库中存储日期和时间


除了旧式的java.util.Date，我们还可以找到另一个java.sql.Date，它继承自java.util.Date，但会自动忽略所有时间相关信息。这个奇葩的设计原因要追溯到数据库的日期与时间类型。

在数据库中，也存在几种日期和时间类型：

	· DATETIME：表示日期和时间；
	· DATE：仅表示日期；
	· TIME：仅表示时间；
	· TIMESTAMP：和DATETIME类似，但是数据库会在创建或者更新记录的时候同时修改TIMESTAMP。

在使用Java程序操作数据库时，我们需要把数据库类型与Java类型映射起来。下表是数据库类型与Java新旧API的映射关系： 

	数据库			对应Java类（旧）			对应Java类（新）
	DATETIME		java.util.Date			LocalDateTime
	DATE			java.sql.Date			LocalDate
	TIME			java.sql.Time			LocalTime
	TIMESTAMP		java.sql.Timestamp		LocalDateTime


--------------------

实际上，在数据库中，我们需要存储的最常用的是时刻（Instant）

因为有了时刻信息，就可以根据用户自己选择的时区，显示出正确的本地时间。

所以，最好的方法是直接用'长整数long'表示，在'数据库中'存储为'BIGINT类型'。

-------------

通过存储一个long型时间戳,用于编写一个timestampToString()的方法,为不同用户以不同的偏好来显示不同的本地时间：	*/
import java.time.*;
import java.time.format.*;
import java.util.Locale;

public class Main {
	public static void main(String[] args) {
		long ts = 1574208900000L;

		System.out.println(timestampToString(ts, Locale.CHINA, "Asia/Shanghai")); // call Function timestampToString
		System.out.println(timestampToString(ts, Locale.US, "America/New_York"));

	}

	// timestampToString(): 为不同用户以不同的偏好来显示不同的本地时间
	static String timestampToString(long epochMilli, Local local, String zoneId) {

		// 1.先建立Instant.ofEpochMilli()
		Instant ins = Instant.ofEpochMilli(epochMilli);

		// 2.建立DateTimeFormatter + 定义显示格式
		DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT); // 设置格式

		// 3.初始化DateTimeFormatterの地区/匹配ofInstant(Instant, ZoneId())
		return f.withLocale(local).format(ZonedDateTime.ofInstant(ins, ZoneId.of(zoneId))); 

		
		// return DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT).withLocal(local).format(ZonedDateTime.ofInstant(ins, ZoneId.of(zoneId)));
	}
}


/*
对上述方法进行调用，结果如下：

	2019年11月20日 上午8:15
	Nov 19, 2019, 7:15 PM

*/



/*	=== 最佳实践 の 小结 === 


1.处理日期和时间时，尽量使用新的java.time包；

2.在数据库中存储时间戳时，尽量使用long型时间戳，它具有省空间，效率高，不依赖数据库的优点。


*/















